﻿using System.IO;

namespace LS.Screening.UI.Common
{
    public class MinioFileOperater
    {
        public string RootPath => AppConfig.Instance.SystemCode;

        string buckerName = "test";
        /// <summary>
        /// 桶名称
        /// </summary>
        public string BucketName => buckerName;

        private MinioService service = null;

        public string BaseDirectory => RootPath;

        public MinioFileOperater()
        {
            service = new MinioService();
        }

        private string GetPath(string storeageName)
        {
            if (storeageName.StartsWith(RootPath))
            {
                return storeageName.Replace("\\", "/");
            }
            return RootPath + "/" + storeageName.Replace("\\", "/");
        }

        private static string GetFormatPath(string storeageName)
        {
            return storeageName.Replace("\\", "/");
        }

        private async Task<bool> ExistsBucket(string bucketName)
        {
            return await service.CheckBucketExistAsync(bucketName);
        }

        public async Task<bool> DeleteAsync(string storeageName)
        {
            return await service.RemoveObjectAsync(BucketName, GetPath(storeageName));
        }

        public async Task<bool> ExistsAsync(string storeageName)
        {
            return await ExistsAsync(storeageName, null);
        }

        public async Task<bool> ExistsAsync(string storeageName, string targetBucketName, bool useDefaultRootPath = true)
        {
            return await service.ObjectsExistsAsync(targetBucketName ?? BucketName, useDefaultRootPath ? GetPath(storeageName) : GetFormatPath(storeageName));
        }

        public async Task ReadAsync(string storeageName, Action<Stream> action)
        {
            if (string.IsNullOrEmpty(storeageName))
            {
                throw new Exception("给定的文件名不能为空: storeageName=" + (storeageName ?? "null"));
            }
            await ReadAsync(storeageName, action, null);
        }

        public async Task ReadAsync(string storeageName, Action<Stream> action, string bucketName = null)
        {
            if (string.IsNullOrEmpty(storeageName))
            {
                throw new Exception("给定的文件名不能为空: storeageName=" + (storeageName ?? "null"));
            }
            await service.GetObjectAsync(bucketName ?? BucketName, string.IsNullOrEmpty(bucketName) ? GetPath(storeageName) : GetFormatPath(storeageName), s =>
            {
                action?.Invoke(s);
            });
        }

        public async Task<byte[]> ReadAsync(string file)
        {
            byte[] data = null;
            await service.GetObjectAsync(BucketName, GetPath(file), s =>
            {
                data = s.ReadData();
            });
            return data;
        }

        public async Task<bool> CopyObjectAsync(string sourceBucketName, string sourceObjectName, string destObjectName = null, string destBucketName = null)
        {
            return await service.CopyObjectAsync(sourceBucketName, GetFormatPath(sourceObjectName), destBucketName ?? BucketName, GetPath(destObjectName));
        }

        public async Task<string> SaveAsync(string file, byte[] fileData)
        {
            return await SaveAsync(file, file, fileData);
        }

        public async Task<string> SaveAsync(string file, string storeagePath, byte[] fileData)
        {
            var objectName = GetPath(file);
            var fileStoreageName = GetFormatPath(file);
            using (var stream = new MemoryStream(fileData))
            {
                await service.PutObjectAsync(BucketName, objectName, stream);
                return fileStoreageName;
            }
        }

        public async Task<string> SaveAsync(string file, Stream fileStream, Action<int> mutilPartProcessCallBack = null)
        {
            return await SaveAsync(file, string.Empty, fileStream, mutilPartProcessCallBack);
        }

        public async Task<string> SaveAsync(string file, string storeagePath, Stream fileStream, Action<int> mutilPartProcessCallBack = null)
        {
            try
            {
                service.MutilPartProcessAction = mutilPartProcessCallBack;
                var fileFullPath = Path.Combine(storeagePath, file);
                var objectName = GetPath(fileFullPath);
                var fileStoreageName = GetFormatPath(fileFullPath);
                await service.PutObjectAsync(BucketName, objectName, fileStream);
                return fileStoreageName;
            }
            finally
            {
                service.MutilPartProcessAction = null;
            }
        }

        public async Task<string> SaveAsync(string fileName, byte[] fileData, int index, int partSize, string storeageName, bool isEnd = false)
        {
            return await SaveAsync(fileName, string.Empty, fileData, index, partSize, storeageName, isEnd);
        }

        public async Task<string> SaveAsync(string fileName, string storeagePath, byte[] fileData, int index, int partSize, string storeageName, bool isEnd = false)
        {
            var fileFullPath = Path.Combine(storeagePath, fileName);
            var objectName = GetPath(fileFullPath);
            var fileStoreageName = GetFormatPath(fileFullPath);
            using (var ms = new MemoryStream(fileData))
            {
                await service.PutObjectAsync(BucketName, objectName, ms);
            }

            return fileStoreageName;
        }
    }
}
